/*
 * FILE: write_perm.c
 *
 *modify page read and write permissions
 *
 */

#include <linux/kallsyms.h>

#include "syscall_hook_arm64.h"


/* 17bit of register CR0,
 * set 1 means kernel address space is not allowed to write, set 0 means it can be written
 */
#if defined(__i386__)
	#define CLEAR_CR0_WP { \
		asm ("push %eax\n\t" \
				"mov %cr0, %eax\n\t" \
				"and $0xfffeffff, %eax\n\t" \
				"mov %eax, %cr0\n\t" \
				"pop %eax"); \
	}

	#define SET_CR0_WP { \
		asm ("push %eax\n\t" \
				"mov %cr0, %eax\n\t" \
				"or $0x00010000, %eax\n\t" \
				"mov %eax, %cr0\n\t" \
				"pop %eax");\
	}
#elif defined(__x86_64__)
	#define CLEAR_CR0_WP  { \
		asm ("push %rax\n\t" \
				"mov %cr0, %rax\n\t" \
				"and $0xfffeffff, %eax\n\t" \
				"mov %rax, %cr0\n\t" \
				"pop %rax"); \
	}

	#define SET_CR0_WP  { \
		asm ("push %rax\n\t" \
				"mov %cr0, %rax\n\t" \
				"or $0x00010000, %eax\n\t" \
				"mov %rax, %cr0\n\t" \
				"pop %rax");\
	}
#else //#if defined (__arm__) || defined (__aarch64__)
	#define CLEAR_CR0_WP  { \
	}

	#define SET_CR0_WP  { \
	}
#endif

#if defined(__aarch64__)
void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgrot_t prot);
unsigned long start_rodata, end_rodata;
#endif


void set_kernel_writable(void){
#if defined(__aarch64__)
	disable_write_protection();
#elif defined(__x86_64__)
	//write_cr0(read_cr0() & (~0x10000));
	CLEAR_CR0_WP
#endif
}

void set_kernel_readonly(void){
#if defined(__aarch64__)
	enable_write_protection();
#elif defined(__x86_64__)
	//write_cr0(read_cr0() | 0x10000);
	SET_CR0_WP
#endif
}
